/**
 * 
 */
package binarysearch.passed2;

/**
 * @author michael
 * 
A peak element is an element that is greater than its neighbors.

Given an input array where num[i] ≠ num[i+1], find a peak element and return its index.

The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.

You may imagine that num[-1] = num[n] = -∞.

For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.

click to show spoilers.
Note:

Your solution should be in logarithmic complexity.

 */
public class FindPeakElement {

	/**
	 * 
	 */
	public FindPeakElement() {
		// TODO Auto-generated constructor stub
	}
	
    public int findPeakElement(int[] num) {
        int low = 0;
        int high = num.length - 1;
        while (low < high) {
            int mid = low + (high - low) / 2;
            if (num[mid] < num[mid+1]) {
                low = mid + 1;
            }
            else {
                high = mid;
            }
        }
        return low;
    }

    public int findPeakElement1(int[] num) {
        if (num == null || num.length == 0)
        	return -1;
        
        int result = -1;
        int left = 0;
        int right = num.length - 1;
        while (left < right) {
        	int mid = left + (right - left) / 2;
        	if ((mid == left && num[mid] > num[mid+1]) ||
        		(mid == right && num[mid] > num[mid-1]) ||
        		(mid > left && mid < right && num[mid] > num[mid-1] && num[mid] > num[mid+1])) {
        		result = mid;
        		return result;
        	}
        	else if ((mid == left && num[mid] < num[mid+1]) ||
        			 (mid > left && mid < right && num[mid] < num[mid+1] && num[mid] > num[mid-1])) {
        		left = mid + 1;
        	}
        	else {
        		right = mid - 1;
        	}
        }
        
        return result;
    }
    
    public int findPeakElement2(int[] num) {
        for (int i = 0, j = num.length - 1, mid = j / 2; i < j; mid = (i + j) / 2) {
            if (mid == i) { return num[mid] > num[j] ? mid : j; }
            i = num[mid] < num[mid + 1] ? mid : i;
            j = num[mid] > num[mid + 1] ? mid : j;
        }
        return 0;
    }
    
    public int helper(int[] num,int start,int end){
        if(start == end){
            return start;
        }else if(start+1 == end){
            if(num[start] > num[end]) return start;
            return end;
        }else{

            int m = (start+end)/2;

            if(num[m] > num[m-1] && num[m] > num[m+1]){

                return m;

            }else if(num[m-1] > num[m] && num[m] > num[m+1]){

                return helper(num,start,m-1);

            }else{

                return helper(num,m+1,end);

            }

        }
    }
          
//    //Binary Search: recursion
//    int findPeakElement(const vector<int> &num) {
//        return Helper(num, 0, num.size()-1);
//    }
//    int Helper(const vector<int> &num, int low, int high)
//    {
//        if(low == high)
//            return low;
//        else
//        {
//            int mid1 = (low+high)/2;
//            int mid2 = mid1+1;
//            if(num[mid1] > num[mid2])
//                return Helper(num, low, mid1);
//            else
//                return Helper(num, mid2, high);
//        }
//    }
//    
//    //Binary Search: iteration
//    int findPeakElement(const vector<int> &num) 
//    {
//        int low = 0;
//        int high = num.size()-1;
//
//        while(low < high)
//        {
//            int mid1 = (low+high)/2;
//            int mid2 = mid1+1;
//            if(num[mid1] < num[mid2])
//                low = mid2;
//            else
//                high = mid1;
//        }
//        return low;
//    }
//    
//    //Sequential Search:
//    int findPeakElement(const vector<int> &num) {
//        for(int i = 1; i < num.size(); i ++)
//        {
//            if(num[i] < num[i-1])
//            {// <
//                return i-1;
//            }
//        }
//        return num.size()-1;
//    }
//    
    
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
